//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#ifndef __TESTING_ASM_H__
#define __TESTING_ASM_H__

#include <testing/tp_slot.h>

// Timer Module Register Structure
typedef struct
{
    volatile UInt32   load;       // RW
    volatile UInt32   value;      // RO
    volatile UInt32   control;    // RW
    volatile UInt32   clear;      // WO
} TIMERREGS;

// Interrupt Controller Module Register Structure
typedef struct
{
    volatile UInt32   status;
    volatile UInt32   rawstatus;
    volatile UInt32   enableset;
    volatile UInt32   enableclear;
} INTCREGS;

#define _BIT(n)       (((UInt32)(1)) << (n))

// Timer Control Register Bit Fields
#define TIMER_CTRL_ENABLE       _BIT(7)
#define TIMER_CTRL_DISABLE      (0)
#define TIMER_CTRL_PERIODIC     _BIT(6)
#define TIMER_CTRL_FREERUN      (0)

// timer mod
typedef enum
{
    FREE_RUNNING = TIMER_CTRL_FREERUN,
    PERIODIC     = TIMER_CTRL_PERIODIC,
} TIMER_MODE;

#define APB_BASE      (0x80000000)
#define TIMER1_BASE   (APB_BASE + 0x0C00)
#define TIMER2_BASE   (APB_BASE + 0x0C20)
#define TIMER3_BASE   (APB_BASE + 0x0C80)
#define INTC_BASE     (APB_BASE + 0x0500)
#define TIMER1        ((TIMERREGS *)(TIMER1_BASE))
#define TIMER2        ((TIMERREGS *)(TIMER2_BASE))
#define TIMER3        ((TIMERREGS *)(TIMER3_BASE))

// Interrupt Controller
#define INTC          ((INTCREGS *)(INTC_BASE))

#define INTC_TC3OINTR_BIT       22

#define LH7A400_BASE_CLOCK      (14745600)

EXTERN_C inline void __cdecl GetCycleCount(TIMESTAMP * pTsp, int bReset = 0)
{
    if (bReset) {
        TIMER3->load     = 0xffff;
        TIMER3->control |= TIMER_CTRL_ENABLE;           //start timer
    }

    // Read TIMER3
    pTsp->high = 0;
    pTsp->low  = 0xffff - TIMER3->value;
}

EXTERN_C inline void timepeg_stamp(TIMESTAMP *pstamp, int bReset = 0)
{
    GetCycleCount(pstamp, bReset);
}

// add two timepegs
inline void timepeg_add(TIMESTAMP* padd, TIMESTAMP* pacc)
{
    pacc->high += padd->high;
    pacc->low  += padd->low;
    if (pacc->low < padd->low) {
        pacc->high++;
    }
}

// sub two timepegs
inline void timepeg_sub(TIMESTAMP* psub, TIMESTAMP* pacc)
{
    pacc->low -= psub->low;
}

EXTERN_C void timepeg_asm();

#define TIMEPEG_ASM(_M_name)                    \
    do {                                        \
        ASM("call   _timepeg_asm;");            \
    } while (0);

#endif
